home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2005 October / PCWOCT05.iso / Software / FromTheMag / XAMPP 1.4.14 / xampp-win32-1.4.14-installer.exe / xampp / php / pear / HTML / QuickForm / hierselect.php < prev    next >
PHP Script  |  2004-10-01  |  16KB  |  441 lines

  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4: */
  3. // +----------------------------------------------------------------------+
  4. // | PHP version 4.0                                                      |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 1997-2004 The PHP Group                                |
  7. // +----------------------------------------------------------------------+
  8. // | This source file is subject to version 2.0 of the PHP license,       |
  9. // | that is bundled with this package in the file LICENSE, and is        |
  10. // | available at through the world-wide-web at                           |
  11. // | http://www.php.net/license/2_02.txt.                                 |
  12. // | If you did not receive a copy of the PHP license and are unable to   |
  13. // | obtain it through the world-wide-web, please send a note to          |
  14. // | license@php.net so we can mail you a copy immediately.               |
  15. // +----------------------------------------------------------------------+
  16. // | Authors: Herim Vasquez <vasquezh@iro.umontreal.ca>                   |
  17. // |          Bertrand Mansion <bmansion@mamasam.com>                     |
  18. // +----------------------------------------------------------------------+
  19. //
  20. // $Id: hierselect.php,v 1.10 2004/06/15 10:51:42 mansion Exp $
  21.  
  22. require_once('HTML/QuickForm/group.php');
  23. require_once('HTML/QuickForm/select.php');
  24.  
  25. /**
  26.  * Class to dynamically create two or more HTML Select elements
  27.  * The first select changes the content of the second select and so on.
  28.  * This element is considered as a group. Selects will be named
  29.  * groupName[0], groupName[1], groupName[2]...
  30.  *
  31.  * @author       Herim Vasquez <vasquezh@iro.umontreal.ca>
  32.  * @author       Bertrand Mansion <bmansion@mamasam.com>
  33.  * @version      1.0
  34.  * @since        PHP4.04pl1
  35.  * @access       public
  36.  */
  37. class HTML_QuickForm_hierselect extends HTML_QuickForm_group
  38. {   
  39.     // {{{ properties
  40.  
  41.     /**
  42.      * Options for all the select elements
  43.      *
  44.      * Format is a bit more complex as we need to know which options
  45.      * are related to the ones in the previous select:
  46.      *
  47.      * Ex:
  48.      * // first select
  49.      * $select1[0] = 'Pop';
  50.      * $select1[1] = 'Classical';
  51.      * $select1[2] = 'Funeral doom';
  52.      *
  53.      * // second select
  54.      * $select2[0][0] = 'Red Hot Chil Peppers';
  55.      * $select2[0][1] = 'The Pixies';
  56.      * $select2[1][0] = 'Wagner';
  57.      * $select2[1][1] = 'Strauss';
  58.      * $select2[2][0] = 'Pantheist';
  59.      * $select2[2][1] = 'Skepticism';
  60.      *
  61.      * // If only need two selects 
  62.      * //     - and using the depracated functions
  63.      * $sel =& $form->addElement('hierselect', 'cds', 'Choose CD:');
  64.      * $sel->setMainOptions($select1);
  65.      * $sel->setSecOptions($select2);
  66.      *
  67.      * //     - and using the new setOptions function
  68.      * $sel =& $form->addElement('hierselect', 'cds', 'Choose CD:');
  69.      * $sel->setOptions(array($select1, $select2));
  70.      *
  71.      * // If you have a third select with prices for the cds
  72.      * $select3[0][0][0] = '15.00$';
  73.      * $select3[0][0][1] = '17.00$';
  74.      * etc
  75.      *
  76.      * // You can now use
  77.      * $sel =& $form->addElement('hierselect', 'cds', 'Choose CD:');
  78.      * $sel->setOptions(array($select1, $select2, $select3));
  79.      * 
  80.      * @var       array
  81.      * @access    private
  82.      */
  83.     var $_options = array();
  84.     
  85.     /**
  86.      * Number of select elements on this group
  87.      *
  88.      * @var       int
  89.      * @access    private
  90.      */
  91.     var $_nbElements = 0;
  92.  
  93.     /**
  94.      * The javascript used to set and change the options
  95.      *
  96.      * @var       string
  97.      * @access    private
  98.      */
  99.     var $_js = "<script type=\"text/javascript\">\n//<![CDATA[\n";
  100.     
  101.     /**
  102.     * The javascript array name
  103.     */
  104.     var $_jsArrayName = '';
  105.  
  106.     // }}}
  107.     // {{{ constructor
  108.  
  109.     /**
  110.      * Class constructor
  111.      * 
  112.      * @param     string    $elementName    (optional)Input field name attribute
  113.      * @param     string    $elementLabel   (optional)Input field label in form
  114.      * @param     mixed     $attributes     (optional)Either a typical HTML attribute string 
  115.      *                                      or an associative array. Date format is passed along the attributes.
  116.      * @param     mixed     $separator      (optional)Use a string for one separator,
  117.      *                                      use an array to alternate the separators.
  118.      * @access    public
  119.      * @return    void
  120.      */
  121.     function HTML_QuickForm_hierselect($elementName=null, $elementLabel=null, $attributes=null, $separator=null)
  122.     {
  123.         $this->HTML_QuickForm_element($elementName, $elementLabel, $attributes);
  124.         $this->_persistantFreeze = true;
  125.         if (isset($separator)) {
  126.             $this->_separator = $separator;
  127.         }
  128.         $this->_type = 'hierselect';
  129.         $this->_appendName = true;
  130.     } //end constructor
  131.  
  132.     // }}}
  133.     // {{{ setOptions()
  134.  
  135.     /**
  136.      * Initialize the array structure containing the options for each select element.
  137.      * Call the functions that actually do the magic.
  138.      *
  139.      * @param     array    $options    Array of options defining each element
  140.      *
  141.      * @access    public
  142.      * @return    void
  143.      */
  144.     function setOptions($options)
  145.     {
  146.         $this->_options = $options;
  147.  
  148.         if (empty($this->_elements)) {
  149.             $this->_nbElements = count($this->_options);
  150.             $this->_createElements();
  151.         } else {
  152.             // setDefaults has probably been called before this function
  153.             // check if all elements have been created
  154.             $totalNbElements = count($this->_options);
  155.             for ($i = $this->_nbElements; $i < $totalNbElements; $i ++) {
  156.                 $this->_elements[] =& new HTML_QuickForm_select($i, null, array(), $this->getAttributes());
  157.                 $this->_nbElements++;
  158.             }
  159.         }
  160.         
  161.         $this->_setOptions();
  162.         $this->_setJS();
  163.     } // end func setMainOptions
  164.  
  165.     // }}}
  166.     // {{{ setMainOptions()
  167.     
  168.     /**
  169.      * Sets the options for the first select element. Deprecated. setOptions() should be used.
  170.      *
  171.      * @param     array     $array    Options for the first select element
  172.      *
  173.      * @access    public
  174.      * @return    void
  175.      */
  176.     function setMainOptions($array)
  177.     {
  178.         $this->_options[0] = $array;
  179.  
  180.         if (empty($this->_elements)) {
  181.             $this->_nbElements = 2;
  182.             $this->_createElements();
  183.         }
  184.     } // end func setMainOptions
  185.     
  186.     // }}}
  187.     // {{{ setSecOptions()
  188.     
  189.     /**
  190.      * Sets the options for the second select element. Deprecated. setOptions() should be used.
  191.      * The main _options array is initialized and the _setOptions function is called.
  192.      *
  193.      * @param     array     $array    Options for the second select element
  194.      *
  195.      * @access    public
  196.      * @return    void
  197.      */
  198.     function setSecOptions($array)
  199.     {
  200.         $this->_options[1] = $array;
  201.  
  202.         if (empty($this->_elements)) {
  203.             $this->_nbElements = 2;
  204.             $this->_createElements();
  205.         } else {
  206.             // setDefaults has probably been called before this function
  207.             // check if all elements have been created
  208.             $totalNbElements = 2;
  209.             for ($i = $this->_nbElements; $i < $totalNbElements; $i ++) {
  210.                 $this->_elements[] =& new HTML_QuickForm_select($i, null, array(), $this->getAttributes());
  211.                 $this->_nbElements++;
  212.             }
  213.         }
  214.         
  215.         $this->_setOptions();
  216.         $this->_setJS();
  217.     } // end func setSecOptions
  218.     
  219.     // }}}
  220.     // {{{ _setOptions()
  221.     
  222.     /**
  223.      * Sets the options for each select element
  224.      *
  225.      * @access    private
  226.      * @return    void
  227.      */
  228.     function _setOptions()
  229.     {
  230.         $toLoad = '';
  231.         foreach (array_keys($this->_elements) AS $key) {
  232.             if (eval("return isset(\$this->_options[{$key}]{$toLoad});") ) {
  233.                 $array = eval("return \$this->_options[{$key}]{$toLoad};");
  234.                 if (is_array($array)) {
  235.                     $select =& $this->_elements[$key];
  236.                     $select->_options = array();
  237.                     $select->loadArray($array);
  238.  
  239.                     $value  = is_array($v = $select->getValue()) ? $v[0] : key($array);
  240.                     $toLoad .= '[\''.$value.'\']';
  241.                 }
  242.             }
  243.         }
  244.     } // end func _setOptions
  245.     
  246.     // }}}
  247.     // {{{ setValue()
  248.  
  249.     /**
  250.      * Sets values for group's elements
  251.      * 
  252.      * @param     array     $value    An array of 2 or more values, for the first,
  253.      *                                the second, the third etc. select
  254.      *
  255.      * @access    public
  256.      * @return    void
  257.      */
  258.     function setValue($value)
  259.     {
  260.         $this->_nbElements = count($value);
  261.         parent::setValue($value);
  262.         $this->_setOptions();
  263.     } // end func setValue
  264.     
  265.     // }}}
  266.     // {{{ _createElements()
  267.  
  268.     /**
  269.      * Creates all the elements for the group
  270.      * 
  271.      * @access    private
  272.      * @return    void
  273.      */
  274.     function _createElements()
  275.     {
  276.         for ($i = 0; $i < $this->_nbElements; $i++) {
  277.             $this->_elements[] =& new HTML_QuickForm_select($i, null, array(), $this->getAttributes());
  278.         }
  279.     } // end func _createElements
  280.  
  281.     // }}}
  282.     // {{{ _setJS()
  283.     
  284.     /**
  285.      * Set the JavaScript for each select element (excluding de main one).
  286.      *
  287.      * @access    private
  288.      * @return    void
  289.      */
  290.     function _setJS()
  291.     {
  292.         $js      = '';
  293.         $this->_jsArrayName = 'hs_' . $this->getName();
  294.         for ($i = 1; $i < $this->_nbElements; $i++) {
  295.             $this->_setJSArray($this->_jsArrayName, $this->_options[$i], $js);
  296.         }
  297.     } // end func _setJS
  298.     
  299.     // }}}
  300.     // {{{ _setJSArray()
  301.     
  302.     /**
  303.      * Recursively builds the JavaScript array defining the options that a select
  304.      * element can have.
  305.      *
  306.      * @param       string      $grpName    Group Name attribute
  307.      * @param       array       $options    Select element options
  308.      * @param       string      $js         JavaScript definition is build using this variable
  309.      * @param       string      $optValue   The value for the current JavaScript option
  310.      *
  311.      * @access      private
  312.      * @return      void
  313.      */
  314.     function _setJSArray($grpName, $options, &$js, $optValue = '')
  315.     {
  316.         if (is_array($options)) {
  317.             $js = '';
  318.             // For a hierselect containing 3 elements:
  319.             //      if option 1 has been selected for the 1st element
  320.             //      and option 3 has been selected for the 2nd element,
  321.             //      then the javascript array containing the values to load 
  322.             //      on the 3rd element will have the following name:   grpName_1_3
  323.             $name  = ($optValue === '') ? $grpName : $grpName.'_'.$optValue;
  324.             foreach($options AS $k => $v) {
  325.                 $this->_setJSArray($name, $v, $js, $k);
  326.             }
  327.             
  328.             // if $js !== '' add it to the JavaScript
  329.             $this->_js .= ($js !== '') ? $name." = {\n".$js."\n}\n" : '';
  330.             $js = '';
  331.         } else {
  332.             // $js empty means that we are adding the first element to the JavaScript.
  333.             if ($js != '') {
  334.                 $js .= ",\n";
  335.             }
  336.             $js .= '"'.$optValue.'":"'.$options.'"';
  337.         }
  338.     }
  339.  
  340.     // }}}
  341.     // {{{ toHtml()
  342.  
  343.     /**
  344.      * Returns Html for the group
  345.      * 
  346.      * @access      public
  347.      * @return      string
  348.      */
  349.     function toHtml()
  350.     {
  351.         if ($this->_flagFrozen) {
  352.             $this->_js = '';
  353.         } else {
  354.             // set the onchange attribute for each element
  355.             $keys               = array_keys($this->_elements);
  356.             $nbElements         = count($keys);
  357.             $nbElementsUsingFnc = $nbElements - 1; // last element doesn't need it
  358.             for ($i = 0; $i < $nbElementsUsingFnc; $i++) {
  359.                 $select =& $this->_elements[$keys[$i]];
  360.                 $select->updateAttributes(
  361.                     array('onChange' => 'swapOptions(this, \''.$this->getName().'\', '.$keys[$i].', '.$nbElements.', \''.$this->_jsArrayName.'\');')
  362.                 );
  363.             }
  364.             
  365.             // create the js function to call
  366.             if (!defined('HTML_QUICKFORM_HIERSELECT_EXISTS')) {
  367.                 $this->_js .= "function swapOptions(frm, grpName, eleIndex, nbElements, arName)\n"
  368.                              ."{\n"
  369.                              ."    var n = \"\";\n"
  370.                              ."    var ctl;\n\n"
  371.                              ."    for (var i = 0; i < nbElements; i++) {\n"
  372.                              ."        ctl = frm.form[grpName+'['+i+']'];\n"
  373.                              ."        if (!ctl) {\n"
  374.                              ."            ctl = frm.form[grpName+'['+i+'][]'];\n"
  375.                              ."        }\n"
  376.                              ."        if (i <= eleIndex) {\n"
  377.                              ."            n += \"_\"+ctl.value;\n"
  378.                              ."        } else {\n"
  379.                              ."            ctl.length = 0;\n"
  380.                              ."        }\n"
  381.                              ."    }\n\n"
  382.                              ."    var t = eval(\"typeof(\"+arName + n +\")\");\n"
  383.                              ."    if (t != 'undefined') {\n"
  384.                              ."        var the_array = eval(arName+n);\n"
  385.                              ."        var j = 0;\n"
  386.                              ."        n = eleIndex + 1;\n"
  387.                              ."        ctl = frm.form[grpName+'['+ n +']'];\n"
  388.                              ."        if (!ctl) {\n"
  389.                              ."            ctl = frm.form[grpName+'['+ n +'][]'];\n"
  390.                              ."        }\n"
  391.                              ."        for (var i in the_array) {\n"
  392.                              ."            opt = new Option(the_array[i], i, false, false);\n"
  393.                              ."            ctl.options[j++] = opt;\n"
  394.                              ."        }\n"
  395.                              ."    }\n"
  396.                              ."}\n";
  397.                 define('HTML_QUICKFORM_HIERSELECT_EXISTS', true);
  398.             }
  399.             $this->_js .= "//]]>\n</script>\n";
  400.         }
  401.         include_once('HTML/QuickForm/Renderer/Default.php');
  402.         $renderer =& new HTML_QuickForm_Renderer_Default();
  403.         $renderer->setElementTemplate('{element}');
  404.         parent::accept($renderer);
  405.         return $this->_js.$renderer->toHtml();
  406.     } // end func toHtml
  407.  
  408.     // }}}
  409.     // {{{ accept()
  410.  
  411.    /**
  412.     * Accepts a renderer
  413.     *
  414.     * @param object     An HTML_QuickForm_Renderer object
  415.     * @param bool       Whether a group is required
  416.     * @param string     An error message associated with a group
  417.     * @access public
  418.     * @return void 
  419.     */
  420.     function accept(&$renderer, $required = false, $error = null)
  421.     {
  422.         $renderer->renderElement($this, $required, $error);
  423.     } // end func accept
  424.  
  425.     // }}}
  426.     // {{{ onQuickFormEvent()
  427.  
  428.     function onQuickFormEvent($event, $arg, &$caller)
  429.     {
  430.         if ('updateValue' == $event) {
  431.             // we need to call setValue() so that the secondary option
  432.             // matches the main option
  433.             return HTML_QuickForm_element::onQuickFormEvent($event, $arg, $caller);
  434.         } else {
  435.             return parent::onQuickFormEvent($event, $arg, $caller);
  436.         }
  437.     } // end func onQuickFormEvent
  438.  
  439.     // }}}    
  440. } // end class HTML_QuickForm_hierselect
  441. ?>